#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
"""

__author__ = "Bumbl"
__version__ = "milestone1"
__license__ = "GPLv2"

import sqlite3
from time import strftime
import os
import sys
import evas
import ecore
import ecore.evas
import edje
import etk

WIDTH = 480
HEIGHT = 640
TITLE = "OMoney"
WM_NAME = "OMoney"
WM_CLASS = "main"
CONFIGDIR = os.path.expanduser("~") + "/.omoney/"
DATABASE = "transactionhistory.sqlite"
EDJE_DIR = "/usr/share/omoney/"
EDJE_MAIN = "omgui.edj"
CURRENCY_SYMBOL = "€"



class Money(object):
    """ Class used for operating with Money """
    def __init__(self,configdir = CONFIGDIR, database=DATABASE):
        self.__testConfigDirExists(configdir)
        self.__database = configdir + database                                       
        self.__connectToDatabase()
        self.__importHistory() 
        self.__money = self.__calculateTotalMoney()
                  
    def getMoney(self):
        """Gets the value of __money"""  
        return self.__money
   
   
    def __testConfigDirExists(self,dir=CONFIGDIR):
        if not os.path.exists(CONFIGDIR):
            os.mkdir(CONFIGDIR)
    
    def __connectToDatabase(self):
        """Open connection to database"""
        if not os.path.exists(self.__database):
            self.__connection = sqlite3.connect(self.__database)
            self.__c = self.__connection.cursor()
            self.__c.execute("""create table money (date text, time text, value real, purpose text, location_fuzzy text, location_gps text)""")
            self.__c.execute("""create table valueallmymoney (date text, value real )""")
            self.__connection.commit()
        else:
            self.__connection = sqlite3.connect(self.__database)
            self.__c = self.__connection.cursor()
                    
    def __addToDatabase(self,date,time,value,purpose,location_fuzzy,location_gps):
        """Add a new row to the database *internal use*"""
        self.__c.execute("""""")
        t = (date, time, value, purpose, location_fuzzy, location_gps)
        self.__c.execute("""insert into money values (?,?,?,?,?,?)""",t)
        self.__c.close()
        self.__connection.commit()
        
    def doTransaction(self,value,purpose,location_fuzzy):
        date = self.__getDate()
        time = self.__getTime()
        location_gps = "--"
        self.__addToDatabase(date=date, time=time, value=value, purpose=purpose, location_fuzzy=location_fuzzy, location_gps=location_gps)
        self.__addDeductMoney(value)
            
    def __importHistory(self):
        """Import the transactionhistory"""
        self.__history = []
        self.__c.execute("""select * from money order by date""")
        for __row in self.__c:
            self.__history.append(__row)
        return self.__history

    def getHistory(self):
        """Gets History"""
        __history = self.__importHistory()
        return __history
                     
    def __getTime(self):
        """Gets current time"""
        __time = strftime("%H:%M:%S")
        return __time
    
    def __getDate(self):
        """Gets current date"""
        __date = strftime("%d.%m.%Y")
        return __date
    
    def __calculateTotalMoney(self):
        """Calculates the value of __money"""
        self.__money = 0
        __i = 0
        while __i < len(self.__history):
            self.__money = self.__money + self.__history[__i][2]
            __i = __i + 1
        return self.__money
    
    def __addDeductMoney(self,value):
        self.__money = self.__money + value
        
    def testValue(self,value):
        try:
            value = float(value.strip().replace(',', '.'))
            return value
        except:
            print "Error only numbers"
            return "Error only numbers"
        
          
        
class OMGui(object):
    """The GUI"""
    def __init__(self, evas_canvas):
        self.evas_obj = evas_canvas.evas_obj
        self.f = EDJE_DIR + EDJE_MAIN
        self.__main_group()
        self.money = Money()
        self.__setMoneyText()
        self.value = None
        self.purpose = None
        self.location_fuzzy = None
        
           
    
    def __main_group(self):
        try:
            self.main_group = edje.Edje(self.evas_obj.evas, file=self.f,
                                        group="main")
        except edje.EdjeLoadError, e:
            raise SystemExit("error loading %s: %s" % (self.f, e))

        self.main_group.size = self.evas_obj.evas.size
        self.evas_obj.data["main"] = self.main_group
        self.main_group.show()
        self.main_group.on_key_down_add(self.on_key_down)
        self.main_group.focus = True

        self.main_group.signal_callback_add("Exit", "*", self.icon_main_selected)
        self.main_group.signal_callback_add("New", "*", self.icon_main_selected)
        self.main_group.signal_callback_add("History", "*", self.icon_main_selected)
        self.main_group.signal_callback_add("Settings", "*", self.icon_main_selected)
    
    def __new_group(self):
        try:
            self.new_group = edje.Edje(self.evas_obj.evas, file=self.f,
                                        group="new")
        except edje.EdjeLoadError, e:
            raise SystemExit("error loading %s: %s" % (self.f, e))
        
        self.new_group.size = self.evas_obj.evas.size
        self.evas_obj.data["new"] = self.new_group
        self.new_group.on_key_down_add(self.on_key_down)

        self.new_group.signal_callback_add("Save", "*", self.icon_new_selected)
        self.new_group.signal_callback_add("Back", "*", self.icon_new_selected)
       
        def input_value(text):
           self.value = text.text
        self.textbox1 = etk.Embed(self.evas_obj.evas)
        self.entry1 = etk.Entry()
        self.textbox1.add(self.entry1)
        self.textbox1.show_all()
        self.new_group.part_swallow("entry1", self.textbox1.object)
        self.entry1.connect("text-changed", input_value)
        
        def input_purpose(text):
           self.purpose = text.text
        self.textbox2 = etk.Embed(self.evas_obj.evas)
        self.entry2 = etk.Entry()
        self.textbox2.add(self.entry2)
        self.textbox2.show_all()
        self.new_group.part_swallow("entry2", self.textbox2.object)
        self.entry2.connect("text-changed", input_purpose)

        def input_location_fuzzy(text):
           self.location_fuzzy = text.text
        self.textbox3 = etk.Embed(self.evas_obj.evas)
        self.entry3 = etk.Entry()
        self.textbox3.add(self.entry3)
        self.textbox3.show_all()
        self.new_group.part_swallow("entry3", self.textbox3.object)
        self.entry3.connect("text-changed", input_location_fuzzy)
    
    def __history_group(self):
        try:
            self.history_group = edje.Edje(self.evas_obj.evas, file=self.f,
                                        group="history")
        except edje.EdjeLoadError, e:
            raise SystemExit("error loading %s: %s" % (self.f, e))
        
        self.history_group.size = self.evas_obj.evas.size
        self.evas_obj.data["history"] = self.history_group
        self.history_group.on_key_down_add(self.on_key_down)

        self.history_group.signal_callback_add("Back", "*", self.icon_history_selected)
        
    def __error_group(self,error_text):
        try:
            self.error_group = edje.Edje(self.evas_obj.evas, file=self.f,
                                        group="error")
        except edje.EdjeLoadError, e:
            raise SystemExit("error loading %s: %s" % (self.f, e))

        self.error_group.size = self.evas_obj.evas.size
        self.evas_obj.data["error"] = self.error_group
        self.error_group.show()
        self.error_group.on_key_down_add(self.on_key_down)

        self.error_group.signal_callback_add("Back", "*", self.icon_error_selected)
        self.error_group.part_text_set("text_error",error_text)

    def __settings_group(self):
        try:
            self.settings_group = edje.Edje(self.evas_obj.evas, file=self.f,
                                        group="settings")
        except edje.EdjeLoadError, e:
            raise SystemExit("error loading %s: %s" % (self.f, e))
        
        self.settings_group.size = self.evas_obj.evas.size
        self.evas_obj.data["settings"] = self.settings_group
        self.settings_group.on_key_down_add(self.on_key_down)

        self.settings_group.signal_callback_add("Back", "*", self.icon_settings_selected)

    def __testError_group(self,test):
        if isinstance(test, str):
            self.__error_group(test)
            return False
        else:
            return test

    def __setMoneyText(self):
        __text_label_money = self.money.getMoney()
        __text_label_money = str(__text_label_money)
        __text_label_money = __text_label_money + " " + CURRENCY_SYMBOL
        self.main_group.part_text_set("label_money",__text_label_money)
    
    def __setHistoryTable(self,data):
        self.__data = data
        if not len(self.__data) == 0:
            self.__cols = len(self.__data[0]) -1
            self.__rows = len(self.__data) + 1
            self.history_table = etk.Embed(self.evas_obj.evas) 
            self.table = etk.Table(cols=self.__cols, rows=self.__rows)
            self.__row = 0
            self.__col = 0
            self.__label = [None] * ((self.__cols) * self.__rows)
            self.__counter = 0
            for heading in ["Date", "Time", "Money", "Purpose", "Location"]:
                self.__label[self.__counter] = etk.Label(text="<font_size=16>" + heading + "</font_size>")
                self.table.attach_default(self.__label[self.__counter], self.__col, self.__col, self.__row, self.__row)
                self.__col = self.__col + 1
                self.__counter = self.__counter + 1
            self.__row = self.__row + 1
            self.__col = 0
            self.__counter = 0
            self.__counter_avoid_gps = 0
            for dataset in self.__data:
                for value in dataset:
                    if self.__counter_avoid_gps < 5 and not self.__counter_avoid_gps == 2:
                        self.__label[self.__counter] = etk.Label(text="<font_size=14>" + str(value) + "</font_size>")
                        self.table.attach_default(self.__label[self.__counter], self.__col, self.__col, self.__row, self.__row)
                        self.__col = self.__col + 1
                        self.__counter = self.__counter + 1
                        self.__counter_avoid_gps = self.__counter_avoid_gps +1
                    elif self.__counter_avoid_gps == 2:
                        self.__label[self.__counter] = etk.Label(text="<font_size=14>" + str(value) + CURRENCY_SYMBOL + "</font_size>")
                        self.table.attach_default(self.__label[self.__counter], self.__col, self.__col, self.__row, self.__row)
                        self.__col = self.__col + 1
                        self.__counter = self.__counter + 1
                        self.__counter_avoid_gps = self.__counter_avoid_gps +1
                        
                self.__col = 0
                self.__row = self.__row + 1
                self.__counter_avoid_gps = 0
                
            self.history_table.add(self.table)
            self.history_table.show_all()
            self.history_group.part_swallow("table_history", self.history_table.object)
    
    def __doTransaction(self,value,purpose,location_fuzzy):
        __value = self.__testError_group(self.money.testValue(value))
        if __value == False:
            print "Transaction failed. Look at the error Message"
        else:       
            __purpose = purpose
            __location_fuzzy = location_fuzzy
            self.money.doTransaction(__value, __purpose, __location_fuzzy)
            self.__clearEntry()
        
    def __clearEntry(self):
        self.entry1.clear()
        self.entry2.clear()
        self.entry3.clear()

    def on_key_down(self, obj, event):
        if event.keyname in ("F6", "f"):
            self.evas_obj.fullscreen = not self.evas_obj.fullscreen
        elif event.keyname == "Escape":
            ecore.main_loop_quit()
        elif event.keyname == "q":
            ecore.main_loop_quit()

    def icon_main_selected(self,edje_obj, signal, source):
        if signal == "Exit":
            print "Exit"
            ecore.main_loop_quit()
        elif signal == "New":
            print "New Transaction"
            self.__new_group()
            self.main_group.hide()
            self.evas_obj.x_window_virtual_keyboard_state_set(4)
            self.new_group.show()
        elif signal == "History":
            print "History"
            self.__history_group()
            self.__setHistoryTable(self.money.getHistory())
            self.main_group.hide()
            self.history_group.show()
        elif signal == "Settings":
            print "Settings"
            self.__settings_group()
            self.main_group.hide()
            self.settings_group.show()

    def icon_new_selected(self,edje_obj, signal, source):
        if signal == "Back":
            print "Back from New Transaction"
            self.evas_obj.x_window_virtual_keyboard_state_set(1)
            self.new_group.hide()
            self.main_group.show()
        elif signal == "Save":
            print "Save"
            self.evas_obj.x_window_virtual_keyboard_state_set(1)
            self.__doTransaction(self.value, self.purpose, self.location_fuzzy)
            self.new_group.hide()
            self.main_group.show()
            self.__setMoneyText()


    def icon_history_selected(self,edje_obj, signal, source):        
        if signal == "Back":
            print "Back from history"
            self.history_group.hide()
            self.main_group.show()

    def icon_error_selected(self,edje_obj, signal, source):        
        if signal == "Back":
            print "Back from history"
            self.error_group.hide()
            self.new_group.show()   
            self.evas_obj.x_window_virtual_keyboard_state_set(4)   

    def icon_settings_selected(self,edje_obj, signal, source):        
        if signal == "Back":
            print "Back from settings"
            self.settings_group.hide()
            self.main_group.show()

class EvasCanvas(object):
    """The basics"""
    def __init__(self, fullscreen, engine, size):
        if options.engine == "x11":
            evas = ecore.evas.SoftwareX11
        elif options.engine == "x11-16":
            if ecore.evas.engine_type_supported_get("software_x11_16"):
                evas = ecore.evas.SoftwareX11_16
            else:
                print "warning: x11-16 is not supported, fallback to x11"
                evas = ecore.evas.SoftwareX11

        self.evas_obj = evas(w=size[0], h=size[1])
        self.evas_obj.callback_delete_request = self.on_delete_request
        self.evas_obj.callback_resize = self.on_resize

        self.evas_obj.title = TITLE
        self.evas_obj.name_class = (WM_NAME, WM_CLASS)
        self.evas_obj.fullscreen = fullscreen
        self.evas_obj.size = size
        self.evas_obj.show()
     

    def on_resize(self, evas_obj):
        x, y, w, h = evas_obj.evas.viewport
        size = (w, h)
        for key in evas_obj.data.keys():
            evas_obj.data[key].size = size

    def on_delete_request(self, evas_obj):
        ecore.main_loop_quit()


####
#The Main Program
####
            
if __name__ == "__main__":
    from optparse import OptionParser

    def parse_geometry(option, opt, value, parser):
        try:
            w, h = value.split("x")
            w = int(w)
            h = int(h)
        except Exception, e:
            raise optparse.OptionValueError("Invalid format for %s" % option)
        parser.values.geometry = (w, h)

    usage = "usage: %prog [options]"
    op = OptionParser(usage=usage)
    op.add_option("-e", "--engine", type="choice",
                  choices=("x11", "x11-16"), default="x11-16",
                  help=("which display engine to use (x11, x11-16), "
                        "default=%default"))
    op.add_option("-n", "--no-fullscreen", action="store_true",
                  help="do not launch in fullscreen")
    op.add_option("-g", "--geometry", type="string", metavar="WxH",
                  action="callback", callback=parse_geometry,
                  default=(WIDTH, HEIGHT),
                  help="use given window geometry")
    op.add_option("-f", "--fps", type="int", default=50,
                  help="frames per second to use, default=%default")


    # Handle options and create output window
    options, args = op.parse_args()
    edje.frametime_set(1.0 / options.fps)
    canvas = EvasCanvas(fullscreen=not options.no_fullscreen,
                        engine=options.engine,
                        size=options.geometry)
    view = OMGui(canvas)
    ecore.main_loop_begin()